# Bibliotecas
import yfinance as yf
import pandas as pd
import plotly.graph_objects as go
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error
from sklearn.cluster import KMeans
from math import sqrt
Carteira de Fundos de Investimento Imobiliário¶
A carteira é composta dos fundos mais rentáveis do primeiro semestre de 2023 de acordo com o Estadão e dos fundos presentes em duas carteiras sugeridas pelo Banco do Brasil para setembro de 2023.
https://einvestidor.estadao.com.br/mercado/fundos-imobiliarios-mais-rentaveis-selic-investimentos/
https://www.bb.com.br/docs/portal/upb/CarteiraFII.pdf
# Fundos mais rentáveis do primeiro semestre de 2023
fii_mais_rentaveis = ['MGHT11.SA', 'KIVO11.SA', 'KNRE11.SA', 'HABT11.SA', 'VOTS11.SA', 'JPPA11.SA', 'RBOP11.SA', 'URPR11.SA', 'RZAK11.SA']
# Cotação do ano de 2023 até o momento
data_inicio = "2023-01-01"
data_fim = "2023-10-02"
# Baixar as cotações dos ativos
for i, ativo in enumerate(fii_mais_rentaveis):
data = yf.download(ativo, start=data_inicio, end=data_fim)
plt.figure(figsize=(12, 6))
plt.plot(data['Adj Close'], label=ativo)
plt.title(f"Cotação de {ativo} em 2023", fontsize=16)
plt.xlabel("Data",fontsize=13)
plt.ylabel("Preço de Fechamento Ajustado", fontsize=13)
plt.xticks(fontsize=13)
plt.yticks(fontsize=13)
plt.grid(True)
plt.show()
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
carteira_fii_renda = ['KFOF11.SA', 'XPSF11.SA', 'HGCR11.SA', 'PLCR11.SA', 'RECR11.SA', 'VGIP11.SA', 'MFII11.SA', 'TGAR11.SA']
# Cotação do ano de 2023 até o momento
data_inicio = "2023-01-01"
data_fim = "2023-10-02"
# Baixar as cotações dos ativos
for i, ativo in enumerate(carteira_fii_renda):
data = yf.download(ativo, start=data_inicio, end=data_fim)
plt.figure(figsize=(12, 6))
plt.plot(data['Adj Close'], label=ativo)
plt.title(f"Cotação de {ativo} em 2023", fontsize=16)
plt.xlabel("Data",fontsize=13)
plt.ylabel("Preço de Fechamento Ajustado", fontsize=13)
plt.xticks(fontsize=13)
plt.yticks(fontsize=13)
plt.grid(True)
plt.show()
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
carteira_fii_ganho = ['RZTR11.SA', 'JSRE11.SA', 'PVBI11.SA', 'RBRF11.SA', 'BRCO11.SA', 'RBRL11.SA', 'HGBS11.SA']
# Cotação do ano de 2023 até o momento
data_inicio = "2023-01-01"
data_fim = "2023-10-02"
# Baixar as cotações dos ativos
for i, ativo in enumerate(carteira_fii_ganho):
data = yf.download(ativo, start=data_inicio, end=data_fim)
plt.figure(figsize=(12, 6))
plt.plot(data['Adj Close'], label=ativo)
plt.title(f"Cotação de {ativo} em 2023", fontsize=16)
plt.xlabel("Data",fontsize=13)
plt.ylabel("Preço de Fechamento Ajustado", fontsize=13)
plt.xticks(fontsize=13)
plt.yticks(fontsize=13)
plt.grid(True)
plt.show()
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
# Conjunto com todos os ativos sem repetição
ativos = set(fii_mais_rentaveis + carteira_fii_renda + carteira_fii_ganho)
# Converte o conjunto em uma lista
ativos = list(ativos)
print(ativos)
['RBRF11.SA', 'PLCR11.SA', 'MGHT11.SA', 'KIVO11.SA', 'RZTR11.SA', 'JPPA11.SA', 'MFII11.SA', 'RBOP11.SA', 'HABT11.SA', 'RBRL11.SA', 'VOTS11.SA', 'RZAK11.SA', 'KNRE11.SA', 'HGBS11.SA', 'KFOF11.SA', 'JSRE11.SA', 'PVBI11.SA', 'XPSF11.SA', 'RECR11.SA', 'URPR11.SA', 'BRCO11.SA', 'HGCR11.SA', 'VGIP11.SA', 'TGAR11.SA']
# Lista de ativos
ativos = ['VGIP11.SA', 'RBRF11.SA', 'KFOF11.SA', 'PVBI11.SA', 'MFII11.SA', 'HGCR11.SA', 'RBOP11.SA', 'HABT11.SA', 'TGAR11.SA', 'MGHT11.SA', 'RECR11.SA', 'PLCR11.SA', 'KIVO11.SA', 'HGBS11.SA', 'JPPA11.SA', 'VOTS11.SA', 'XPSF11.SA', 'RBRL11.SA', 'BRCO11.SA', 'RZTR11.SA', 'JSRE11.SA', 'RZAK11.SA', 'KNRE11.SA', 'URPR11.SA']
# Dicionário para armazenar os indicadores de cada ativo
indicadores_por_ativo = {}
for ativo in ativos:
estoque = yf.Ticker(ativo)
informacoes = estoque.info
indicadores = {
'P/L (Relação Preço-Lucro)': informacoes.get('trailingPE', None),
'Dividend Yield (Rendimento de Dividendo)': informacoes.get('dividendYield', None),
'Cap. de Mercado': informacoes.get('marketCap', None),
'Volume Médio': informacoes.get('averageVolume', None)
}
def formatar_valor(valor, tipo='moeda'):
if valor is None:
return None
if tipo == 'moeda':
return f"R$ {valor:,.2f}"
elif tipo == 'porcentagem':
return f"{valor * 100:.2f}%"
for chave in indicadores:
if "Yield" in chave :
indicadores[chave] = formatar_valor(indicadores[chave], 'porcentagem')
elif "Cap. de Mercado" in chave:
indicadores[chave] = formatar_valor(indicadores[chave], 'moeda')
indicadores_por_ativo[ativo] = indicadores
# Criar DataFrame
dfs = []
for ativo, indicadores in indicadores_por_ativo.items():
df = pd.DataFrame(list(indicadores.items()), columns=['Indicador', 'Valor'])
df['Ativo'] = ativo
dfs.append(df)
resultado_df = pd.concat(dfs, ignore_index=True)
print(resultado_df)
Indicador Valor Ativo 0 P/L (Relação Preço-Lucro) None VGIP11.SA 1 Dividend Yield (Rendimento de Dividendo) 8.68% VGIP11.SA 2 Cap. de Mercado None VGIP11.SA 3 Volume Médio 22999 VGIP11.SA 4 P/L (Relação Preço-Lucro) 40.92 RBRF11.SA .. ... ... ... 91 Volume Médio 17074 KNRE11.SA 92 P/L (Relação Preço-Lucro) NaN URPR11.SA 93 Dividend Yield (Rendimento de Dividendo) NaN URPR11.SA 94 Cap. de Mercado NaN URPR11.SA 95 Volume Médio 22982.0 URPR11.SA [96 rows x 3 columns]
resultado = resultado_df.pivot(index=['Indicador'], columns=['Ativo'], values='Valor').fillna('N/A')
resultado
| Ativo | BRCO11.SA | HABT11.SA | HGBS11.SA | HGCR11.SA | JPPA11.SA | JSRE11.SA | KFOF11.SA | KIVO11.SA | KNRE11.SA | MFII11.SA | ... | RBRF11.SA | RBRL11.SA | RECR11.SA | RZAK11.SA | RZTR11.SA | TGAR11.SA | URPR11.SA | VGIP11.SA | VOTS11.SA | XPSF11.SA |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Indicador | |||||||||||||||||||||
| Cap. de Mercado | N/A | R$ 380,305,024.00 | R$ 2,292,574,720.00 | R$ 1,632,622,592.00 | N/A | R$ 1,581,637,632.00 | N/A | N/A | N/A | R$ 387,944,832.00 | ... | R$ 1,119,636,608.00 | R$ 613,201,536.00 | R$ 2,307,029,504.00 | N/A | N/A | N/A | N/A | N/A | N/A | N/A |
| Dividend Yield (Rendimento de Dividendo) | 8.39% | 14.61% | 10.35% | 12.27% | 13.98% | 7.26% | 9.63% | N/A | 235.27% | 13.66% | ... | 8.19% | 8.49% | 8.24% | N/A | N/A | N/A | N/A | 8.68% | 10.78% | 10.60% |
| P/L (Relação Preço-Lucro) | N/A | N/A | 9.966072 | N/A | N/A | 12.264091 | N/A | N/A | N/A | 7.955745 | ... | 40.92 | 13.957381 | 7.252702 | N/A | N/A | N/A | N/A | N/A | N/A | N/A |
| Volume Médio | 27358 | 13870 | 22233 | 37753 | 2782 | 39365 | 15577 | 2404.0 | 17074 | 5314 | ... | 40049 | 12565 | 60364 | 48364.0 | 22414.0 | 34291.0 | 22982.0 | 22999 | 74 | 78513 |
4 rows × 24 columns
Candlestick¶
fig = go.Figure(data=[go.Candlestick(x=df.index,
open=df['Open'],
high=df['High'],
low=df['Low'],
close=df['Close'])])
fig.update_layout(title=f'Gráfico de Candlestick para {ativo}')
fig.update_xaxes(
tickangle=-45, # Ângulo de rotação dos rótulos para melhor legibilidade
dtick='M1', # Exibe rótulos de data mensais
tickformat='%Y-%m' # Formato da data
)
fig.show()
Candlestick de alta (bullish): O preço de abertura é inferior ao preço de fechamento. O corpo é representado de forma sólida na cor verde e indica pressão de compra.
Candlestick de baixa (bearish): O preço de abertura é superior ao preço de fechamento. corpo é representado de forma sólida na cor vermelha e indica pressão de compra.
ativos = ['VGIP11.SA', 'RBRF11.SA', 'KFOF11.SA', 'PVBI11.SA', 'MFII11.SA', 'HGCR11.SA', 'RBOP11.SA', 'HABT11.SA', 'TGAR11.SA', 'MGHT11.SA', 'RECR11.SA', 'PLCR11.SA', 'KIVO11.SA', 'HGBS11.SA', 'JPPA11.SA', 'VOTS11.SA', 'XPSF11.SA', 'RBRL11.SA', 'BRCO11.SA', 'RZTR11.SA', 'JSRE11.SA', 'RZAK11.SA', 'KNRE11.SA', 'URPR11.SA']
resultados_candles = []
for ativo in ativos:
df = yf.download(ativo, start='2023-09-01', end='2023-10-02')
ultimo_candlestick = 'Alta' if df['Close'].iloc[-1] > df['Open'].iloc[-1] else 'Baixa'
resultados_candles.append({'Ativo': ativo, 'Último Candlestick': ultimo_candlestick})
df_candles = pd.DataFrame(resultados_candles)
print(df_candles)
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
Ativo Último Candlestick
0 VGIP11.SA Baixa
1 RBRF11.SA Alta
2 KFOF11.SA Alta
3 PVBI11.SA Alta
4 MFII11.SA Alta
5 HGCR11.SA Alta
6 RBOP11.SA Baixa
7 HABT11.SA Alta
8 TGAR11.SA Alta
9 MGHT11.SA Baixa
10 RECR11.SA Alta
11 PLCR11.SA Alta
12 KIVO11.SA Baixa
13 HGBS11.SA Alta
14 JPPA11.SA Alta
15 VOTS11.SA Baixa
16 XPSF11.SA Baixa
17 RBRL11.SA Baixa
18 BRCO11.SA Alta
19 RZTR11.SA Alta
20 JSRE11.SA Alta
21 RZAK11.SA Alta
22 KNRE11.SA Baixa
23 URPR11.SA Alta
# Tabela dinâmica com a contagem de alta e baixa
pivot_table = pd.pivot_table(df_resultados_candles, index=['Último Candlestick'], aggfunc='count')
# Renomeiar a coluna 'Ativo' para 'Contagem'
pivot_table = pivot_table.rename(columns={'Ativo': 'Contagem'})
# Imprimir a tabela dinâmica
print(pivot_table)
Contagem Último Candlestick Alta 16 Baixa 8
# Filtrar fundos com candlestick de alta (bullish)
fundos_candle_alta = df_candles[df_candles['Último Candlestick'] == 'Alta']
# Filtrar fundos com candlestick de baixa (bearish)
fundos_candle_baixa = df_candles[df_candles['Último Candlestick'] == 'Baixa']
# Imprimir a lista de fundos com candlestick de alta
print("Fundos com Candlestick de Alta:")
print(fundos_candle_alta['Ativo'].tolist())
# Imprimir a lista de fundos com candlestick de baixa
print("\nFundos com Candlestick de Baixa:")
print(fundos_candle_baixa['Ativo'].tolist())
Fundos com Candlestick de Alta: ['RBRF11.SA', 'KFOF11.SA', 'PVBI11.SA', 'MFII11.SA', 'HGCR11.SA', 'HABT11.SA', 'TGAR11.SA', 'RECR11.SA', 'PLCR11.SA', 'HGBS11.SA', 'JPPA11.SA', 'BRCO11.SA', 'RZTR11.SA', 'JSRE11.SA', 'RZAK11.SA', 'URPR11.SA'] Fundos com Candlestick de Baixa: ['VGIP11.SA', 'RBOP11.SA', 'MGHT11.SA', 'KIVO11.SA', 'VOTS11.SA', 'XPSF11.SA', 'RBRL11.SA', 'KNRE11.SA']
RSI¶
O RSI varia de 0 a 100. Tradicionalmente, o RSI é considerado sobrecomprado quando acima de 70 e sobrevendido quando abaixo de 30. Valores acima de 70 podem indicar que o ativo está em um estado de sobrecompra, o que poderia levar a uma reversão de preço em breve. Valores abaixo de 30 podem indicar que o ativo está em um estado de sobrevenda, o que poderia levar a uma reversão de preço para cima em breve.
# Lista de ativos
ativos = ['VGIP11.SA', 'RBRF11.SA', 'KFOF11.SA', 'PVBI11.SA', 'MFII11.SA', 'HGCR11.SA', 'RBOP11.SA', 'HABT11.SA', 'TGAR11.SA', 'MGHT11.SA', 'RECR11.SA', 'PLCR11.SA', 'KIVO11.SA', 'HGBS11.SA', 'JPPA11.SA', 'VOTS11.SA', 'XPSF11.SA', 'RBRL11.SA', 'BRCO11.SA', 'RZTR11.SA', 'JSRE11.SA', 'RZAK11.SA', 'KNRE11.SA', 'URPR11.SA']
def calculo_rsi(dados, tempo):
delta = dados.diff()
up, down = delta.copy(), delta.copy()
up[up < 0] = 0
down[down > 0] = 0
roll_up = up.rolling(window=tempo).mean()
roll_down = down.abs().rolling(window=tempo).mean()
rs = roll_up / roll_down
rsi = 100 - (100 / (1 + rs))
return rsi
resultados_rsi = []
for i, ativo in enumerate(ativos):
df = yf.download(ativo, start='2023-09-01', end='2023-10-01')
df['RSI'] = calculo_rsi(df['Close'], 14)
ultimo_rsi = df['RSI'].iloc[-1]
if ultimo_rsi < 30:
estado_rsi = 'Sobrevenda (RSI < 30)'
elif ultimo_rsi > 70:
estado_rsi = 'Sobrecompra (RSI > 70)'
else:
estado_rsi = '30 <= RSI <= 70'
resultados_rsi.append({'Ativo': ativo, 'Estado RSI': estado_rsi})
# Criando um DataFrame com os resultados
df_rsi = pd.DataFrame(resultados_rsi)
print(df_rsi)
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
Ativo Estado RSI
0 VGIP11.SA Sobrevenda (RSI < 30)
1 RBRF11.SA 30 <= RSI <= 70
2 KFOF11.SA 30 <= RSI <= 70
3 PVBI11.SA 30 <= RSI <= 70
4 MFII11.SA 30 <= RSI <= 70
5 HGCR11.SA Sobrecompra (RSI > 70)
6 RBOP11.SA 30 <= RSI <= 70
7 HABT11.SA 30 <= RSI <= 70
8 TGAR11.SA Sobrecompra (RSI > 70)
9 MGHT11.SA Sobrevenda (RSI < 30)
10 RECR11.SA 30 <= RSI <= 70
11 PLCR11.SA 30 <= RSI <= 70
12 KIVO11.SA 30 <= RSI <= 70
13 HGBS11.SA 30 <= RSI <= 70
14 JPPA11.SA 30 <= RSI <= 70
15 VOTS11.SA 30 <= RSI <= 70
16 XPSF11.SA 30 <= RSI <= 70
17 RBRL11.SA 30 <= RSI <= 70
18 BRCO11.SA 30 <= RSI <= 70
19 RZTR11.SA 30 <= RSI <= 70
20 JSRE11.SA 30 <= RSI <= 70
21 RZAK11.SA 30 <= RSI <= 70
22 KNRE11.SA 30 <= RSI <= 70
23 URPR11.SA 30 <= RSI <= 70
# Lista de ativos
ativos = ['VGIP11.SA', 'RBRF11.SA', 'KFOF11.SA', 'PVBI11.SA', 'MFII11.SA', 'HGCR11.SA', 'RBOP11.SA', 'HABT11.SA', 'TGAR11.SA', 'MGHT11.SA', 'RECR11.SA', 'PLCR11.SA', 'KIVO11.SA', 'HGBS11.SA', 'JPPA11.SA', 'VOTS11.SA', 'XPSF11.SA', 'RBRL11.SA', 'BRCO11.SA', 'RZTR11.SA', 'JSRE11.SA', 'RZAK11.SA', 'KNRE11.SA', 'URPR11.SA']
for i, ativo in enumerate(ativos):
df = yf.download(ativo, start='2023-09-01', end='2023-10-01')
df['RSI'] = calculo_rsi(df['Close'], 14)
fig = go.Figure()
fig.add_trace(go.Scatter(x=df.index, y=df['RSI'], mode='lines', name='RSI', line=dict(width=1.5)))
# Adiciona uma linha com o preço do ativo
fig.add_trace(go.Scatter(x=df.index, y=df['Close'], mode='lines', name='Preço', line=dict(width=1.5, color='black')))
fig.update_layout(title=f"RSI e Preço para {ativo}",
yaxis_title="RSI / Preço",
xaxis_rangeslider_visible=False,
yaxis_fixedrange=False)
# Ajusta a frequência dos rótulos de data no eixo x
fig.update_xaxes(
tickangle=-45, # Ângulo de rotação dos rótulos para melhor legibilidade
dtick='M1', # Exibe rótulos de data mensais
tickformat='%Y-%m' # Formato da data
)
fig.show()
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
# Filtrar fundos com sobrevenda
df_rsi_sobrevenda = df_rsi[df_rsi['Estado RSI'] == 'Sobrevenda (RSI < 30)']
# Imprimir a lista de fundos com sobrevenda
print("Fundos com sobrevenda:")
print(df_rsi_sobrevenda['Ativo'].tolist())
# Filtrar fundos com sobrecompra
df_rsi_sobrecompra = df_rsi[df_rsi['Estado RSI'] == 'Sobrecompra (RSI > 70)']
# Imprimir a lista de fundos com sobrecompra
print("\nFundos com sobrecompra:")
print(df_rsi_sobrecompra['Ativo'].tolist())
Fundos com sobrevenda: ['VGIP11.SA', 'MGHT11.SA'] Fundos com sobrecompra: ['HGCR11.SA', 'TGAR11.SA']
MACD¶
Cruzamento da Linha MACD e Linha de Sinal: Quando a linha MACD cruza acima da linha de sinal, é um sinal de compra, o que indica uma possÃvel reversão de tendência de baixa para alta. Por outro lado, quando a linha MACD cruza abaixo da linha de sinal, é um sinal de venda, o que indica uma possÃvel reversão de tendência de alta para baixa.
# Função para o cálculo para o MACD
def calculo_macd(dados):
short_window = 12
long_window = 26
signal_window = 9
# ewm do pandas para o cálculo da média móvel exponencialmente ponderada
short_media = dados.ewm(span=short_window, adjust=False).mean()
long_media = dados.ewm(span=long_window, adjust=False).mean()
macd = short_media - long_media
signal = macd.ewm(span=signal_window, adjust=False).mean()
return macd, signal
for ativo in ativos:
df = yf.download(ativo, start='2023-09-01', end='2023-10-02')
df['MACD'], df['Signal'] = calculo_macd(df['Close'])
fig = go.Figure()
fig.add_trace(go.Scatter(x=df.index, y=df['MACD'], mode='lines', name='MACD', line=dict(width=1.5)))
fig.add_trace(go.Scatter(x=df.index, y=df['Signal'], mode='lines', name='Signal', line=dict(width=1.5, dash='dash')))
fig.update_layout(title=f"MACD para {ativo}",
yaxis_title="MACD",
xaxis_rangeslider_visible=False,
yaxis_fixedrange=False)
fig.show()
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
[*********************100%***********************] 1 of 1 completed
Fundos com MACD no cruzamento de alta: MFII11.SA, HGCR11.SA, TGAR11.SA, PLCR11.SA, KIVO11.SA, HGBS11.SA, VOTS11.SA, RZTR11.SA, KNRE11.SA
Fundos com MACD no cruzamento de baixa: VGIP11.SA, RBRF11.SA, KFOF11.SA, PVBI11.SA, RBOP11.SA, HABT11.SA, MGHT11.SA, RECR11.SA, JPPA11.SA, XPSF11.SA, RBRL11.SA, BRCO11.SA, JSRE11.SA, RZKA11.SA, URPR11.SA
Correlações¶
# Lista de ativos
ativos = ['VGIP11.SA', 'RBRF11.SA', 'KFOF11.SA', 'PVBI11.SA', 'MFII11.SA', 'HGCR11.SA', 'RBOP11.SA', 'HABT11.SA', 'TGAR11.SA', 'MGHT11.SA', 'RECR11.SA', 'PLCR11.SA', 'KIVO11.SA', 'HGBS11.SA', 'JPPA11.SA', 'VOTS11.SA', 'XPSF11.SA', 'RBRL11.SA', 'BRCO11.SA', 'RZTR11.SA', 'JSRE11.SA', 'RZAK11.SA', 'KNRE11.SA', 'URPR11.SA']
# Baixar cotações de setembro de 2023
data = yf.download(ativos, start="2023-09-01", end="2023-10-02")['Adj Close']
# Análise da Correlação
matriz_correl = data.corr()
plt.figure(figsize=(12, 10))
# Heatmap da matriz de correlação
sns.heatmap(matriz_correl, annot=True, cmap='coolwarm', vmin=-1, vmax=1)
plt.title('Heatmap da Matriz de Correlação')
plt.tight_layout()
plt.show()
[*********************100%***********************] 24 of 24 completed
Retornos dos Ativos¶
ativos = ['VGIP11.SA', 'RBRF11.SA', 'KFOF11.SA', 'PVBI11.SA', 'MFII11.SA', 'HGCR11.SA', 'RBOP11.SA', 'HABT11.SA', 'TGAR11.SA', 'MGHT11.SA', 'RECR11.SA', 'PLCR11.SA', 'KIVO11.SA', 'HGBS11.SA', 'JPPA11.SA', 'VOTS11.SA', 'XPSF11.SA', 'RBRL11.SA', 'BRCO11.SA', 'RZTR11.SA', 'JSRE11.SA', 'RZAK11.SA', 'KNRE11.SA', 'URPR11.SA']
# Inicia o DataFrame vazio para armezenar os retornos dos ativos
retorno = pd.DataFrame()
# Retorno do mês de setembro
for ativo in ativos:
data = yf.Ticker(ativo)
start_date = "2023-09-01"
end_date = "2023-10-02"
# DataFrame data que contém os preços de fechamento diários dos ativos
data = data.history(start=start_date, end=end_date)
# Função pct.change calcula os retornos percentuais diários do ativo
data['Retorno'] = data['Close'].pct_change()
# adicionar os retornos no DataFrame geral
retorno[ativo] = data['Retorno']
# Remove as linhas que contêm valores ausentes (NAs)
retorno = retorno.dropna()
print(retorno)
VGIP11.SA RBRF11.SA KFOF11.SA PVBI11.SA \
Date
2023-01-03 00:00:00-03:00 0.000928 0.010753 0.017371 -0.019569
2023-01-04 00:00:00-03:00 -0.003130 -0.011348 0.000529 -0.005784
2023-01-05 00:00:00-03:00 0.000116 0.000718 0.017992 0.021444
2023-01-06 00:00:00-03:00 -0.000465 -0.002724 0.013645 -0.013400
2023-01-09 00:00:00-03:00 0.006863 -0.012363 -0.019231 -0.013582
... ... ... ... ...
2023-09-25 00:00:00-03:00 -0.001129 -0.041036 -0.038415 0.000000
2023-09-26 00:00:00-03:00 -0.007119 -0.014549 0.004057 -0.003585
2023-09-27 00:00:00-03:00 -0.001480 0.000124 -0.029945 -0.001610
2023-09-28 00:00:00-03:00 0.000342 -0.011289 -0.001282 -0.017259
2023-09-29 00:00:00-03:00 -0.004102 0.007779 0.051230 0.033388
MFII11.SA HGCR11.SA RBOP11.SA HABT11.SA \
Date
2023-01-03 00:00:00-03:00 0.000870 0.029520 -0.001546 0.002125
2023-01-04 00:00:00-03:00 0.005974 -0.000291 -0.006452 0.013506
2023-01-05 00:00:00-03:00 0.002915 -0.010950 0.000000 -0.002313
2023-01-06 00:00:00-03:00 0.004091 -0.001568 -0.006493 0.001987
2023-01-09 00:00:00-03:00 0.012651 0.000393 -0.040817 -0.015313
... ... ... ... ...
2023-09-25 00:00:00-03:00 -0.000425 -0.000928 0.005559 -0.003638
2023-09-26 00:00:00-03:00 0.006485 -0.001672 -0.008866 -0.012134
2023-09-27 00:00:00-03:00 -0.005387 0.003071 -0.006735 -0.004348
2023-09-28 00:00:00-03:00 -0.001593 -0.001763 0.023867 0.015284
2023-09-29 00:00:00-03:00 0.004574 0.006877 -0.010033 0.007527
TGAR11.SA MGHT11.SA ... JPPA11.SA VOTS11.SA \
Date ...
2023-01-03 00:00:00-03:00 -0.018519 0.026253 ... -0.001824 0.057895
2023-01-04 00:00:00-03:00 -0.005086 -0.002147 ... 0.000577 -0.042278
2023-01-05 00:00:00-03:00 -0.010472 0.003944 ... -0.005382 0.005518
2023-01-06 00:00:00-03:00 0.002333 0.017857 ... -0.000193 0.000000
2023-01-09 00:00:00-03:00 -0.001496 0.000526 ... 0.000193 0.016463
... ... ... ... ... ...
2023-09-25 00:00:00-03:00 0.001202 -0.032623 ... 0.000605 -0.002020
2023-09-26 00:00:00-03:00 0.001601 -0.000339 ... -0.002218 -0.021548
2023-09-27 00:00:00-03:00 0.004794 -0.011527 ... -0.001313 0.015574
2023-09-28 00:00:00-03:00 -0.001193 0.010461 ... -0.001517 -0.000240
2023-09-29 00:00:00-03:00 0.020621 -0.002037 ... 0.007092 -0.009946
XPSF11.SA RBRL11.SA BRCO11.SA RZTR11.SA \
Date
2023-01-03 00:00:00-03:00 0.005548 -0.010104 -0.002501 0.000958
2023-01-04 00:00:00-03:00 0.015172 0.002459 -0.012237 -0.000426
2023-01-05 00:00:00-03:00 -0.009511 -0.002576 -0.019598 0.005854
2023-01-06 00:00:00-03:00 -0.010974 0.002214 0.006732 0.001270
2023-01-09 00:00:00-03:00 0.000000 -0.035007 0.004630 0.008243
... ... ... ... ...
2023-09-25 00:00:00-03:00 -0.003521 -0.008023 -0.008743 -0.009358
2023-09-26 00:00:00-03:00 -0.005889 0.005464 -0.009535 0.000508
2023-09-27 00:00:00-03:00 -0.018957 -0.002174 -0.001765 -0.014416
2023-09-28 00:00:00-03:00 0.007246 -0.005447 -0.007474 0.024928
2023-09-29 00:00:00-03:00 -0.002398 0.006572 0.007935 0.013467
JSRE11.SA RZAK11.SA KNRE11.SA URPR11.SA
Date
2023-01-03 00:00:00-03:00 -0.005105 0.021979 -0.016949 -0.006558
2023-01-04 00:00:00-03:00 -0.003991 0.002379 -0.068965 0.005078
2023-01-05 00:00:00-03:00 0.008300 0.003460 0.018519 0.000909
2023-01-06 00:00:00-03:00 0.000426 -0.012218 0.036364 0.002120
2023-01-09 00:00:00-03:00 -0.023975 0.014963 -0.017544 0.000705
... ... ... ... ...
2023-09-25 00:00:00-03:00 -0.006910 -0.002710 -0.018182 -0.004174
2023-09-26 00:00:00-03:00 -0.014302 0.002500 0.000000 -0.002042
2023-09-27 00:00:00-03:00 -0.005621 -0.000325 0.018519 -0.003985
2023-09-28 00:00:00-03:00 -0.008808 0.003796 0.000000 0.001189
2023-09-29 00:00:00-03:00 0.007427 0.007888 -0.018182 0.012419
[187 rows x 24 columns]
def calcula_estat(column):
return pd.Series({
'Média': column.mean(),
'Mediana': column.median(),
'Desvio Padrão (populacional)': column.std(ddof=0),
'Desvio Padrão (amostral)': column.std(),
'Variância (populacional)': column.var(ddof=0),
'Variância (amostral)': column.var(),
'Coeficiente de Variação': (column.std() / column.mean()) if column.mean() != 0 else 0
})
estatisticas_retorno = retorno.select_dtypes(include=['float64']).apply(calcula_estat)
estatisticas_retorno
| VGIP11.SA | RBRF11.SA | KFOF11.SA | PVBI11.SA | MFII11.SA | HGCR11.SA | RBOP11.SA | HABT11.SA | TGAR11.SA | MGHT11.SA | ... | JPPA11.SA | VOTS11.SA | XPSF11.SA | RBRL11.SA | BRCO11.SA | RZTR11.SA | JSRE11.SA | RZAK11.SA | KNRE11.SA | URPR11.SA | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Média | 0.000502 | 0.001248 | 0.001988 | 0.001157 | 0.000665 | 0.000916 | -0.003191 | 0.000844 | 0.000510 | 0.001016 | ... | 0.000338 | 0.000745 | 0.001238 | 0.000997 | 0.001548 | 0.000701 | 0.000736 | 0.000100 | 0.000290 | 0.000083 |
| Mediana | 0.000371 | 0.001912 | 0.000923 | 0.000485 | 0.000472 | 0.000774 | -0.001274 | 0.001056 | 0.000490 | 0.000691 | ... | 0.000393 | 0.000000 | 0.001261 | 0.000571 | 0.000848 | 0.001200 | 0.001292 | 0.000600 | 0.000000 | 0.000308 |
| Desvio Padrão (populacional) | 0.007650 | 0.012587 | 0.014055 | 0.009895 | 0.006820 | 0.005425 | 0.030379 | 0.007065 | 0.007940 | 0.011963 | ... | 0.005648 | 0.014110 | 0.008858 | 0.011291 | 0.010115 | 0.011879 | 0.010718 | 0.010685 | 0.039844 | 0.008102 |
| Desvio Padrão (amostral) | 0.007671 | 0.012621 | 0.014093 | 0.009922 | 0.006838 | 0.005440 | 0.030460 | 0.007084 | 0.007962 | 0.011995 | ... | 0.005663 | 0.014148 | 0.008882 | 0.011321 | 0.010143 | 0.011911 | 0.010747 | 0.010713 | 0.039951 | 0.008124 |
| Variância (populacional) | 0.000059 | 0.000158 | 0.000198 | 0.000098 | 0.000047 | 0.000029 | 0.000923 | 0.000050 | 0.000063 | 0.000143 | ... | 0.000032 | 0.000199 | 0.000078 | 0.000127 | 0.000102 | 0.000141 | 0.000115 | 0.000114 | 0.001588 | 0.000066 |
| Variância (amostral) | 0.000059 | 0.000159 | 0.000199 | 0.000098 | 0.000047 | 0.000030 | 0.000928 | 0.000050 | 0.000063 | 0.000144 | ... | 0.000032 | 0.000200 | 0.000079 | 0.000128 | 0.000103 | 0.000142 | 0.000115 | 0.000115 | 0.001596 | 0.000066 |
| Coeficiente de Variação | 15.282803 | 10.115652 | 7.087718 | 8.576652 | 10.276403 | 5.936066 | -9.545962 | 8.395039 | 15.606476 | 11.811250 | ... | 16.731192 | 19.002782 | 7.174043 | 11.351888 | 6.551122 | 16.990938 | 14.602920 | 107.182365 | 137.560767 | 97.640673 |
7 rows × 24 columns
Previsão de Preço usando Média Móvel¶
ativos = ['VGIP11.SA', 'RBRF11.SA', 'KFOF11.SA', 'PVBI11.SA', 'MFII11.SA', 'HGCR11.SA', 'RBOP11.SA', 'HABT11.SA', 'TGAR11.SA', 'MGHT11.SA', 'RECR11.SA', 'PLCR11.SA', 'KIVO11.SA', 'HGBS11.SA', 'JPPA11.SA', 'VOTS11.SA', 'XPSF11.SA', 'RBRL11.SA', 'BRCO11.SA', 'RZTR11.SA', 'JSRE11.SA', 'RZAK11.SA', 'KNRE11.SA', 'URPR11.SA']
window = 30
for ativo in ativos:
data = yf.download(ativo, start="2023-01-01", end="2023-10-02")
train_size = int(len(data) * 0.8)
train = data['Close'][:train_size]
test = data['Close'][train_size:]
predictions = []
for t in range(len(test)):
if t < window:
predictions.append(train[-(window-t):].mean())
else:
predictions.append(test[t-window:t].mean())
rmse = sqrt(mean_squared_error(test[window:], predictions[window:]))
print(f'Ativo: {ativo}, RMSE: {rmse}')
plt.figure(figsize=(14,7))
plt.plot(train.index, train, label='Treino')
plt.plot(test.index, test, label='Real')
plt.plot(test.index, predictions, label='Previsto')
plt.legend(loc='best')
plt.title(f"Previsão de Preço para {ativo} usando Média Móvel", fontsize=16)
plt.xticks(fontsize=13)
plt.yticks(fontsize=13)
plt.legend(loc='upper left')
plt.grid(True)
#plt.show()
[*********************100%***********************] 1 of 1 completed Ativo: VGIP11.SA, RMSE: 2.662621457553978 [*********************100%***********************] 1 of 1 completed Ativo: RBRF11.SA, RMSE: 3.0509818657001526 [*********************100%***********************] 1 of 1 completed Ativo: KFOF11.SA, RMSE: 2.3618002894888095 [*********************100%***********************] 1 of 1 completed Ativo: PVBI11.SA, RMSE: 1.8435847416361784 [*********************100%***********************] 1 of 1 completed Ativo: MFII11.SA, RMSE: 0.38624549006889647 [*********************100%***********************] 1 of 1 completed Ativo: HGCR11.SA, RMSE: 0.921946284542225 [*********************100%***********************] 1 of 1 completed Ativo: RBOP11.SA, RMSE: 12.53156084458245 [*********************100%***********************] 1 of 1 completed Ativo: HABT11.SA, RMSE: 2.466854822568626 [*********************100%***********************] 1 of 1 completed Ativo: TGAR11.SA, RMSE: 2.7261716980997037 [*********************100%***********************] 1 of 1 completed Ativo: MGHT11.SA, RMSE: 4.5649820367351035 [*********************100%***********************] 1 of 1 completed Ativo: RECR11.SA, RMSE: 1.503881774078767 [*********************100%***********************] 1 of 1 completed Ativo: PLCR11.SA, RMSE: 0.8914985970114468 [*********************100%***********************] 1 of 1 completed Ativo: KIVO11.SA, RMSE: 0.7532170206715817 [*********************100%***********************] 1 of 1 completed Ativo: HGBS11.SA, RMSE: 1.9397436313267375 [*********************100%***********************] 1 of 1 completed Ativo: JPPA11.SA, RMSE: 1.7897148559348275 [*********************100%***********************] 1 of 1 completed Ativo: VOTS11.SA, RMSE: 0.9561584187717067 [*********************100%***********************] 1 of 1 completed Ativo: XPSF11.SA, RMSE: 0.17905890053174656 [*********************100%***********************] 1 of 1 completed Ativo: RBRL11.SA, RMSE: 1.2002321895826225 [*********************100%***********************] 1 of 1 completed Ativo: BRCO11.SA, RMSE: 1.1463005565106712 [*********************100%***********************] 1 of 1 completed Ativo: RZTR11.SA, RMSE: 1.7737150192635334 [*********************100%***********************] 1 of 1 completed Ativo: JSRE11.SA, RMSE: 1.210701539364669
C:\Users\tatia\AppData\Local\Temp\ipykernel_28620\3387628264.py:23: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`). Consider using `matplotlib.pyplot.close()`.
[*********************100%***********************] 1 of 1 completed Ativo: RZAK11.SA, RMSE: 0.35928084246809616 [*********************100%***********************] 1 of 1 completed Ativo: KNRE11.SA, RMSE: 0.015721074734407706 [*********************100%***********************] 1 of 1 completed Ativo: URPR11.SA, RMSE: 2.9514562758153784
Cluster¶
ativos = ['VGIP11.SA', 'RBRF11.SA', 'KFOF11.SA', 'PVBI11.SA', 'MFII11.SA', 'HGCR11.SA', 'RBOP11.SA', 'HABT11.SA', 'TGAR11.SA', 'MGHT11.SA', 'RECR11.SA', 'PLCR11.SA', 'KIVO11.SA', 'HGBS11.SA', 'JPPA11.SA', 'VOTS11.SA', 'XPSF11.SA', 'RBRL11.SA', 'BRCO11.SA', 'RZTR11.SA', 'JSRE11.SA', 'RZAK11.SA', 'KNRE11.SA', 'URPR11.SA']
# Calcular WCSS para diferentes números de clusters
wcss = [] # armazenar uma lista para alocar as distâncias
for i in range(1, 11): # o 11 foi forçado, mas pode mudar.. np-completo... lembre-se
kmeans = KMeans(n_clusters=i, n_init=10, random_state=42)
kmeans.fit(matriz_correl) # Usamos diretamente a matriz de correlação aqui
wcss.append(kmeans.inertia_) ## resultados do inertia
# Plotar WCSS em relação ao número de clusters
plt.figure(figsize=(10,6))
plt.plot(range(1, 11), wcss, marker='o', linestyle='--')
plt.title('Método do Cotovelo')
plt.xlabel('Número de Clusters')
plt.ylabel('WCSS')
plt.grid(True)
plt.show()
# Definir o número de clusters
num_clusters = 5
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=num_clusters) # Rodar a função para o número de cluster definido
nomes = kmeans.fit_predict(matriz_correl) # Alocar os tickers pela correlação
matriz_correl_clustered = matriz_correl.copy() # Copiar a matriz de correlação
matriz_correl_clustered['Cluster'] = nomes # Adicionar nomes como uma nova coluna
matriz_correl_clustered = matriz_correl_clustered.sort_values('Cluster') # Ordenar as linhas pelos clusters
# Criar um DataFrame com os clusters
df_clusters = pd.DataFrame({
'Ticker': matriz_correl.index,
'Cluster': nomes
})
# Ordenar os clusters
df_clusters = df_clusters.sort_values(by='Cluster')
print(df_clusters)
Ticker Cluster 1 HABT11.SA 0 4 JPPA11.SA 0 21 VGIP11.SA 0 20 URPR11.SA 0 10 MGHT11.SA 0 13 RBOP11.SA 0 14 RBRF11.SA 0 18 RZTR11.SA 1 17 RZAK11.SA 1 12 PVBI11.SA 1 15 RBRL11.SA 1 11 PLCR11.SA 2 2 HGBS11.SA 2 3 HGCR11.SA 2 7 KIVO11.SA 2 19 TGAR11.SA 2 0 BRCO11.SA 3 6 KFOF11.SA 3 5 JSRE11.SA 3 16 RECR11.SA 3 23 XPSF11.SA 3 22 VOTS11.SA 4 9 MFII11.SA 4 8 KNRE11.SA 4
c:\Users\tatia\AppData\Local\Programs\Python\Python311\Lib\site-packages\sklearn\cluster\_kmeans.py:1412: FutureWarning: The default value of `n_init` will change from 10 to 'auto' in 1.4. Set the value of `n_init` explicitly to suppress the warning
# Heatmap da Matriz de Correlação com Clusters
plt.figure(figsize=(12, 10))
sns.heatmap(matriz_correl_clustered.drop('Cluster', axis=1), annot=True, cmap='Purples', vmin=-1, vmax=1, yticklabels=matriz_correl_clustered.index)
plt.title('Heatmap da Matriz de Correlação com Clusters')
plt.tight_layout()
plt.show()
# Calcular os retornos diários e eliminar os valores ausentes
retorno = data.pct_change().dropna() # pct_change calcula os retornos percentuais diários
# Calcular o retorno acumulado
retorno_acumulado = (1 + retorno).cumprod()
# Último valor do retorno acumulado
final_retorno_acumulado = retorno_acumulado.iloc[-1]
# Juntar os ativos com o retorno acumulado
df_combinado = pd.concat([df_clusters.set_index('Ticker'), final_retorno_acumulado], axis=1)
# Renomear as colunas
df_combinado.columns = ['Cluster', 'Retorno Acumulado']
# Ordenar os clusters
unique_clusters = df_clusters['Cluster'].unique()
# Selecionar em cada cluster o ativo com maior retorno acumulado
tickers_selecionados = []
for cluster in unique_clusters:
ticker = df_combinado[df_combinado['Cluster'] == cluster]['Retorno Acumulado'].idxmax()
tickers_selecionados.append(ticker)
print("Fundos com maior retorno acumulado de cada cluster:")
for ticker in tickers_selecionados:
print(ticker)
Fundos com maior retorno acumulado de cada cluster: JPPA11.SA RZTR11.SA KFOF11.SA MFII11.SA TGAR11.SA RECR11.SA
# Calcular o retorno da carteira com todos os ativos
portfolio = data.pct_change().dropna().mean(axis=1)
# Calcular o retorno da carteira com os ativos com maior retorno
dados_selecionados = data[tickers_selecionados]
weights = [1/len(tickers_selecionados)] * len(tickers_selecionados) #peso na carteira
portfolio_selecionado = dados_selecionados.pct_change().dropna().dot(weights) # o dot multiplica o valor do retorno pelo peso na carteira
# Calcular o retorno acumulado
retorno_acumulado_all = (1 + portfolio).cumprod()
retorno_acumulado_selected = (1 + portfolio_selecionado).cumprod()
# Plotar o retorno acumulado
plt.figure(figsize=(14, 7))
retorno_acumulado_all.plot(label="Carteira Todos os Tickers", legend=True)
retorno_acumulado_selected.plot(label="Carteira Diferenciada", legend=True)
plt.title('Comparação do Desempenho das Carteiras', fontsize=16)
plt.ylabel('Retorno Cumulativo', fontsize=13)
plt.xlabel('Data', fontsize=13)
plt.legend(loc='best')
plt.xticks(fontsize=13)
plt.yticks(fontsize=13)
plt.grid(True)
plt.show()